package edu.dali.enterprise_test.kits;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.*;
import java.io.StringReader;
import java.io.StringWriter;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class KitUtils {

    /**
     * 包裹外层开具发票报文
     *
     * @param in
     * @param lsh
     * @return
     */
    public static String getAllXml(String in, String taxcode, String lsh) {
        String r = "<?xml version=\"1.0\" encoding=\"utf-8\"?><interface xmlns=\"\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.chinatax.gov.cn/tirip/dataspec/interfaces.xsd\" version=\"DZFP1.0\"><globalInfo><appId>ZZSDZFP</appId><interfaceCode>EI.FPKJ.U.EC.INTRA</interfaceCode><userName>%s</userName><passWord></passWord><requestCode></requestCode><requestTime>%s</requestTime><responseCode></responseCode><dataExchangeId>%s</dataExchangeId><fjh></fjh><jqbh></jqbh></globalInfo><returnStateInfo><returnCode>0000</returnCode><returnMessage></returnMessage></returnStateInfo><Data><dataDescription><zipCode>0</zipCode><encryptCode>0</encryptCode><codeType>0</codeType></dataDescription><content>%s</content></Data></interface>";

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        String datetime = sdf.format(new Date());
        r = String.format(r, taxcode, datetime, lsh, in);
        return r;
    }

    /**
     * 包裹外层签章报文
     *
     * @param lsh
     * @param taxcode
     * @param content
     * @return
     */
    public static String getSignatureXml(String lsh, String taxcode, String content) {
        String xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
                "<interface xmlns=\"\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.chinatax.gov.cn/tirip/dataspec/interfaces.xsd\" version=\"DZFP1.0\">\n" +
                "\t<globalInfo>\n" +
                "\t\t<terminalCode>1</terminalCode>\n" +
                "\t\t<appId>A16D8DBD18EDDD80</appId>\n" +
                "\t\t<version>2.0</version>\n" +
                "\t\t<interfaceCode>ECXML.FPQZ.BC.E.INV</interfaceCode>\n" +
                "\t\t<userName>%s</userName>\n" + //1 税号
                "\t\t<passWord/>\n" +
                "\t\t<taxpayerId>%s</taxpayerId>\n" +//2 税号
                "\t\t<authorizationCode/>\n" +
                "\t\t<requestCode/>\n" +
                "\t\t<requestTime>%s</requestTime>\n" +//3 请求时间
                "\t\t<responseCode/>\n" +
                "\t\t<dataExchangeId>%s</dataExchangeId>\n" + //4 流水号
                "<fjh/>\n" +
                "\t\t<jqbh/>" +
                "\t</globalInfo>\n" +
                "\t<returnStateInfo>\n" +
                "\t\t<returnCode>0000</returnCode>\n" +
                "\t\t<returnMessage/>\n" +
                "\t</returnStateInfo>\n" +
                "\t<Data>\n" +
                "\t\t<dataDescription>\n" +
                "\t\t\t<zipCode>0</zipCode>\n" +
                "\t\t\t<encryptCode>2</encryptCode>\n" +
                "\t\t\t<codeType>CA</codeType>\n" +
                "\t\t</dataDescription>\n" +
                "\t\t<content>%s</content>\n" + //5 内容
                "\t</Data>\n" +
                "</interface>";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        String datetime = sdf.format(new Date());
        return String.format(xml, taxcode, taxcode, datetime, lsh, content);
    }


    /**
     * 对象序列化xml
     *
     * @param rf
     * @param clz
     * @return
     * @throws JAXBException
     * @throws PropertyException
     */
    public static String GetXmlString(Object rf, Class<?> clz) throws JAXBException,
            PropertyException {
        String content;
        JAXBContext context = JAXBContext
                .newInstance(clz);
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
        marshaller.setProperty(Marshaller.JAXB_ENCODING, "utf-8");
        StringWriter writer = new StringWriter();
        marshaller.marshal(rf, writer);
        content = writer.toString();
        return content;
    }

    /**
     * xml序列化为对象
     *
     * @param xml
     * @param clz
     * @return
     * @throws JAXBException
     */
    public static <T> T GetObjectFromXml(String xml, Class<T> clz) throws JAXBException {
        JAXBContext context = JAXBContext
                .newInstance(clz);
        Unmarshaller unmarshaller = context.createUnmarshaller();
//		unmarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
//		unmarshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
//		unmarshaller.setProperty(Marshaller.JAXB_ENCODING, "utf-8");
        T t = (T) unmarshaller.unmarshal(new StringReader(xml));
        return t;
    }


    public static String getExtraXml(String interfaceCode, String in, String taxcode, String lsh) {
        String r = "<?xml version=\"1.0\" encoding=\"utf-8\"?><interface xmlns=\"\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.chinatax.gov.cn/tirip/dataspec/interfaces.xsd\" version=\"DZFP1.0\"><globalInfo><appId>ZZSDZFP</appId><interfaceCode>%s</interfaceCode><userName>%s</userName><passWord></passWord><requestCode></requestCode><requestTime>%s</requestTime><responseCode></responseCode><dataExchangeId>%s</dataExchangeId><fjh></fjh><jqbh></jqbh></globalInfo><returnStateInfo><returnCode>0000</returnCode><returnMessage></returnMessage></returnStateInfo><Data><dataDescription><zipCode>0</zipCode><encryptCode>0</encryptCode><codeType>0</codeType></dataDescription><content>%s</content></Data></interface>";

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        String datetime = sdf.format(new Date());
        r = String.format(r, interfaceCode, taxcode, datetime, lsh, in);
        return r;
    }

    /**
     * 获取两个日期相差的天数
     *
     * @param startDateStr
     * @param endDateStr
     */
    public static int getDayBetweenTwoDate(String startDateStr, String endDateStr) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        int days = 0;
        try {
            Date startDate = simpleDateFormat.parse(startDateStr);
            Date endDate = simpleDateFormat.parse(endDateStr);
            Calendar startCalendar = Calendar.getInstance();
            startCalendar.setTime(startDate);
            Calendar endCalendar = Calendar.getInstance();
            endCalendar.setTime(endDate);
            //计算两个日期相差的天数
            //startCalendar.getTime().getTime()返回long毫秒数形式,毫秒转为秒所以除以1000
            //1天=24小时，1小时=60分，1分=60秒，所以两个时间的差再除以60 * 60 * 24换算成天的形式
            days = ((int) (startCalendar.getTime().getTime() / 1000) - (int) (endCalendar.getTime().getTime() / 1000)) / (60 * 60 * 24);

        } catch (ParseException e) {
            e.printStackTrace();
        }
        return days;
    }

    /**
     * 通过时间秒毫秒数判断两个时间的间隔
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int differentDaysByMillisecond(Date date1, Date date2) {
        int days = (int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24));
        return days;
    }

    public static String HMACSHA256(byte[] data, byte[] key) {
        try {
            SecretKeySpec signingKey = new SecretKeySpec(key, "HmacSHA256");
            Mac mac = Mac.getInstance("HmacSHA256");
            mac.init(signingKey);
            return byte2hex(mac.doFinal(data));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static String byte2hex(byte[] b) {
        StringBuilder hs = new StringBuilder();
        String stmp;
        for (int n = 0; b != null && n < b.length; n++) {
            stmp = Integer.toHexString(b[n] & 0XFF);
            if (stmp.length() == 1)
                hs.append('0');
            hs.append(stmp);
        }
        return hs.toString().toUpperCase();
    }

}
